package com.yuri.news.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.yuri.news.controller.PrivilegeController;
import com.yuri.news.entity.Depa;
import com.yuri.news.entity.Privilege;
import com.yuri.news.entity.PrivilegePack;
import com.yuri.news.entity.Role;
import com.yuri.news.entity.User;
import com.yuri.news.jpa.PrivilegeRepository;
import com.yuri.news.service.ButtonService;
import com.yuri.news.service.DepaService;
import com.yuri.news.service.MenuService;
import com.yuri.news.service.PrivilegeService;
import com.yuri.news.service.RoleService;
import com.yuri.news.service.UserService;

@Service
public class PrivilegeServiceImpl implements PrivilegeService {
	private final Logger logger = LoggerFactory.getLogger(PrivilegeController.class);
	@Autowired
	PrivilegeRepository privilegeRepository;
	@Autowired
	PrivilegeService privilegeService;
	@Autowired
	UserService userService;
	@Autowired
	RoleService roleService;
	@Autowired
	DepaService depaService;
	@Autowired
	MenuService menuService;
	@Autowired
	ButtonService buttonService;

	@Override
	public Boolean savePrivilege(Privilege privilege) {
		logger.info("\n savePrivilege 开始");
		Boolean flag = false;
		// 判断是否存在
		Privilege pri = privilegeRepository
				.findByPrivilegeAccessAndPrivilegeAccessValueAndPrivilegeMasterAndPrivilegeMasterValue(
						privilege.getPrivilegeAccess(), privilege.getPrivilegeAccessValue(),
						privilege.getPrivilegeMaster(), privilege.getPrivilegeMasterValue());
		// 如果没有值
		if (null == pri) {
			privilege.setIsAvailable(true);
			// 保存用户信息
			privilegeRepository.save(privilege);
			flag = true;
		}
		logger.info("\n savePrivilege 结束");
		return flag;
	}

	@Override
	public Boolean deletePrivilege(Privilege privilege) {
		logger.info("\n deletePrivilege 开始");
		Boolean flag = false;
		// 查询是否存在此权限
		Privilege pri = privilegeRepository
				.findByPrivilegeAccessAndPrivilegeAccessValueAndPrivilegeMasterAndPrivilegeMasterValue(
						privilege.getPrivilegeAccess(), privilege.getPrivilegeAccessValue(),
						privilege.getPrivilegeMaster(), privilege.getPrivilegeMasterValue());

		if (pri != null) {
			privilegeRepository.delete(pri);
			flag = true;
		}
		logger.info("\n deletePrivilege 结束");
		return flag;
	}

	@Override
	public Boolean setPrivilegeOperation(Long id) {
		logger.info("\n setPrivilegeOperation 开始");
		Boolean flag = false;
		Optional<Privilege> optional = privilegeRepository.findById(id);

		if (optional.isPresent()) {
			Privilege pri = optional.get();

			if (pri.getIsAvailable()) {
				pri.setIsAvailable(false);
			} else {
				pri.setIsAvailable(true);
			}
			flag = true;
		}
		logger.info("\n setPrivilegeOperation 结束");
		return flag;
	}

	@Override
	public List<PrivilegePack> listAuthorAll(Boolean isAva, Pageable page) {
		
		List<Privilege> privileges = new ArrayList<>();		// 存放查询数据
		// 包装权限
		List<PrivilegePack> privilegePacks = new ArrayList<>();
		
		privileges = privilegeRepository.findByIsAvailable(isAva, page).getContent();
		logger.info("\n 查询所有权限(findAuthorAll) 结果1 privileges = " + privileges);
		if (privileges.size() == 0) {
			return null;
		}
		// 遍历权限
		for (Privilege privilege : privileges) {
			logger.info("\n 查询所有权限(findAuthorAll) 结果2 PrivilegeMaster = " + privilege.getPrivilegeMaster());
			// 设置权限类型
			setPrivilegeClass(getPrivilegePack(privilegePacks, privilege), privilege);
			
			logger.info("\n 查询所有权限(findAuthorAll) 结果3 privilegePack = " + getPrivilegePack(privilegePacks, privilege));
		}
		
		setUserByRole(privilegePacks, isAva);
		// 查询部门和角色看是否有其用户未添加到权限包装里面
		setUserPrivilegePack(privilegePacks);
		
		return privilegePacks;
	}
	
	/**
	 * 获取用户的权限包装
	 * @param privilege		权限信息
	 * @return	此用户的权限包装
	 */
	public PrivilegePack getUserPrack(Privilege privilege) {
		logger.info("\n 获取用户的权限包装(getUserPrack) 开始 privilege = " + privilege);
		PrivilegePack privilegePack = new PrivilegePack();
		/* 查询用户 */
		User user = userService.findUserById(privilege.getPrivilegeMasterValue());
		// 保存user
		privilegePack.setUser(user);
		/* 查询用户结束 */
		logger.info("\n 获取用户的权限包装(getUserPrack) 结束 privilegePack = " + privilegePack);
		return privilegePack;
	}
	
	/**
	 * 获取角色的权限包装
	 * @param privilege		权限信息
	 * @return	此角色的权限包装
	 */
	public PrivilegePack getRolePrack(Privilege privilege) {
		logger.info("\n 获取角色的权限包装(getRolePrack) 开始 privilege = " + privilege);
		PrivilegePack privilegePack = new PrivilegePack();
		/* 查询用户 */
		Role role = roleService.findRoleById(privilege.getPrivilegeMasterValue());
		// 保存user
		privilegePack.setRole(role);
		/* 查询用户结束 */
		logger.info("\n 获取角色的权限包装(getRolePrack) 结束 privilegePack = " + privilegePack);
		return privilegePack;
	}
	
	/**
	 * 获取部门的权限包装
	 * @param privilege		权限信息
	 * @return	此部门的权限包装
	 */
	public PrivilegePack getDepaPrack(Privilege privilege) {
		logger.info("\n 获取角色的权限包装(getRolePrack) 开始 privilege = " + privilege);
		PrivilegePack privilegePack = new PrivilegePack();
		/* 查询角色 */
		Depa depa = depaService.getDepa(privilege.getPrivilegeMasterValue());
		// 保存user
		privilegePack.setDepa(depa);
		/* 查询角色结束 */
		logger.info("\n 获取角色的权限包装(getRolePrack) 结束 privilegePack = " + privilegePack);
		return privilegePack;
	}
	/**
	 * 判断privilegePacks里是否存在此角色的权限包装
	 * @param privilegePacks
	 * @param privilege	权限信息
	 * @return	存在返回引用（不存在返回null）
	 */
	public PrivilegePack judgeRole(List<PrivilegePack> privilegePacks, Privilege privilege) {
		PrivilegePack privilegePack = null;
		// 判断此角色是否已经存在
		for (PrivilegePack pack : privilegePacks) {
			if (pack.getRole() != null && pack.getRole().getId().equals(privilege.getPrivilegeMasterValue())) {
				privilegePack = pack;
				break;
			}
		}
		return privilegePack;
	}
	
	/**
	 * 判断privilegePacks里是否存在此用户的权限包装
	 * @param privilegePacks
	 * @param privilege	权限信息
	 * @return	存在返回引用（不存在返回null）
	 */
	public PrivilegePack judgeUser(List<PrivilegePack> privilegePacks, Privilege privilege) {
		PrivilegePack privilegePack = null;
		// 判断此角色是否已经存在
		for (PrivilegePack pack : privilegePacks) {
			if (pack.getUser() != null && pack.getUser().getId().equals(privilege.getPrivilegeMasterValue())) {
				privilegePack = pack;
				break;
			}
		}
		return privilegePack;
	}
	
	/**
	 * 判断privilegePacks里是否存在此部门的权限包装
	 * @param privilegePacks
	 * @param privilege	权限信息
	 * @return	存在返回引用（不存在返回null）
	 */
	public PrivilegePack judgeDepa(List<PrivilegePack> privilegePacks, Privilege privilege) {
		PrivilegePack privilegePack = null;
		// 判断此角色是否已经存在
		for (PrivilegePack pack : privilegePacks) {
			if (pack.getDepa() != null && pack.getDepa().getId().equals(privilege.getPrivilegeMasterValue())) {
				privilegePack = pack;
				break;
			}
		}
		return privilegePack;
	}
	
	/**
	 * 获取包装类信息
	 * @param privilegePacks 用于判断此权限是否存在于privilegePacks
	 * @param privilege	权限信息
	 * @return 返回包装类的引用
	 */
	public PrivilegePack getPrivilegePack(List<PrivilegePack> privilegePacks, Privilege privilege) {
		// 表示此用户/角色/部门 是否存在包装里面
		Boolean flag = false;
		PrivilegePack privilegePack = null;
		
		switch (privilege.getPrivilegeMaster()) {
		// 如果为用户
		case "user":
			privilegePack = judgeUser(privilegePacks, privilege);
			
			if(null == privilegePack) {
				privilegePack = getUserPrack(privilege);
			}else {
				flag = true;
			}
			break;
		// 如果为角色
		case "role":
			privilegePack = judgeRole(privilegePacks, privilege);

			if(null == privilegePack) {
				privilegePack = getRolePrack(privilege);
			}else {
				flag = true;
			}
			break;
		// 如果为部门
		case "depa":
			privilegePack = judgeDepa(privilegePacks, privilege);

			if(null == privilegePack) {
				privilegePack = getDepaPrack(privilege);
			}else {
				flag = true;
			}
			break;
		default:
			break;
		}
		// 如果不存在则添加
		if(!flag) {
			privilegePacks.add(privilegePack);
		}
		return privilegePack;
	}
	/**
	 * 设置权限类型（菜单或按钮）
	 * @param privilegePack	要设置的包装类信息
	 * @param privilege	权限信息
	 */
	public void setPrivilegeClass(PrivilegePack privilegePack, Privilege privilege) {
		switch (privilege.getPrivilegeAccess()) {
		case "menu":
			privilegePack.setMenus(menuService.getMenu(privilege.getPrivilegeAccessValue()));
			break;
		case "button":
			privilegePack.setButtons(buttonService.getButtonById(privilege.getPrivilegeAccessValue()));
			break;
		default:
			break;
		}
	}
	/**
	 * 根据部门权限设置 用户权限信息
	 * @param privilegePacks 权限包装类
	 * @param isAva	是否可用
	 */
	public void setUserByRole(List<PrivilegePack> privilegePacks, Boolean isAva) {
		List<PrivilegePack> packs = new ArrayList<>();
		
		for(PrivilegePack privilegePack : privilegePacks) {
			List<User> users = null;
			if(privilegePack.getRole() != null) {
				users = userService.findUserByRoleName(privilegePack.getRole().getRoleName(), isAva);
			}else if(privilegePack.getDepa() != null) {
				users = userService.findUserByDepaName(privilegePack.getDepa().getDepaName(), isAva);
			}
			
			if(users != null) {
				for(User user : users) {
					Boolean flag = false;
					PrivilegePack userPack = null;
					for(PrivilegePack pack : privilegePacks) {
						logger.info("\n pack=" + pack);
						if(pack.getUser() != null && pack.getUser().getId().equals(user.getId())) {
							flag = true;
							break;
						}
					}
					if(!flag) {
						userPack = new PrivilegePack();
						userPack.setUser(user);
						packs.add(userPack);
					}
				}
			}
		}
		privilegePacks.addAll(packs);
	}
	
	/**
	 * 设置用户权限（将用户的部门权限和角色权限赋值给用户本身）
	 * @param privilegePacks 所有权限包装类
	 */
	public void setUserPrivilegePack(List<PrivilegePack> privilegePacks) {
		
		for (PrivilegePack pack : privilegePacks) {
			// 如果权限包装的是用户的权限
			logger.info("\n 如果权限包装的是用户的权限");
			if (pack.getUser() != null) {
				// 如果用户有角色 则查询角色权限并添加
				logger.info("\n 如果用户有角色 则查询角色权限并添加");
				if (pack.getUser().getRole() != null) {
					// 遍历他的角色
					logger.info("\n 遍历他的角色");
					List<Role> roles = pack.getUser().getRole();
					// 遍历用户角色
					logger.info("\n 遍历用户角色");
					for (Role role : roles) {
						// 遍历权限包装
						for (int i = 0; i < privilegePacks.size(); i++) {
							// 如果存在角色 并且 此角色与用户拥有的角色一致
							logger.info("\n 如果存在角色 并且 此角色与用户拥有的角色一致");
							if (privilegePacks.get(i).getRole() != null
									&& privilegePacks.get(i).getRole().getId() == role.getId()
									&& privilegePacks.get(i).getRole().getIsAvailable()) {
								// 更新用户的权限
								logger.info("\n 更新用户的权限");
								pack.setMenus(privilegePacks.get(i).getMenus());
								pack.setButtons(privilegePacks.get(i).getButtons());
							}
						}
					}
				}
				// 如果此用户有部门 、、则查询部门权限并添加
				if (pack.getUser().getDepa() != null) {
					// 获取用户部门信息
					Depa depa = pack.getUser().getDepa();
					// 遍历权限包装
					for (int i = 0; i < privilegePacks.size(); i++) {
						// 如果权限包装 里面有此用户的部门
						if (privilegePacks.get(i).getDepa() != null
								&& depa.getId() == privilegePacks.get(i).getDepa().getId()) {
							// 添加权限
							pack.setButtons(privilegePacks.get(i).getButtons());
							pack.setMenus(privilegePacks.get(i).getMenus());
						}
					}

					while (depa.getUpDepa() != null) {
						// 获取上一级部门的信息
						depa = depa.getUpDepa();
						// 遍历权限包装
						for (int i = 0; i < privilegePacks.size(); i++) {
							// 如果权限包装 里面有此用户的部门
							if (privilegePacks.get(i).getDepa() != null
									&& depa.getId() == privilegePacks.get(i).getDepa().getId()) {
								// 添加权限
								pack.setButtons(privilegePacks.get(i).getButtons());
								pack.setMenus(privilegePacks.get(i).getMenus());
							}
						}
					}
					logger.info("\n 查询所有权限(findAuthorAll) 结果6 pack = " + pack);
				}
			}
		}
	}
}
